<!--
//
//  Derived from:
//  Copyright (c) 2009, Google Inc.
//  Proxy Settings, a sample Google extension, by Mike West
//  http://code.google.com/chrome/extensions/samples.html
//  License: BSD
//
//  Copyright (c) 2011 Roy Six
//  http://code.google.com/p/urli/
//  License: LGPL v3.0
//
//  This file is part of urli.
//
//  urli is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  urli is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with urli.  If not, see <http://www.gnu.org/licenses/>.
//
-->

<!DOCTYPE HTML>

<html>

	<head>

		<title>urli Popup</title>

		<!-- CSS -->

		<style>

			/* Initial popup body background color and window size (for 16px images). */

			body {
				background: #EDECEB;
				height: 16px; /* Use 24 for 24px images. */
				width: 82px; /* Use 114 for 24px images.*/
				margin: 5px;
			}

			/* Div for images; displayed by default when the popup opens. */

			div[id="images"] {
				display: inline;
			}

			/* Gives 2px right spacing to images set inline (except for the last). */

			input[type="image"]:not(:last-child) {
				margin-right: 2px;
			}

			/* Disabled class for images, set by updateImages(). */

			input[type="image"].disabled {
				opacity: 0.2;
			}

			/* Enabled class for images, set by updateImages(). */

			input[type="image"].enabled {
				opacity: 1.0;
			}

			/* Div for form; hidden by default when the popup opens. */

			div[id="form"] {
				display: none;
				border-radius: 5px;
				font: 14px/1 "Helvetica Neue", Arial, Helvetica, sans-serif;
				font-weight: normal;
				color: #777777;
				padding: 10px;
				width: 563px;
				box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5); 
				-webkit-transition: background-color 0.5s ease-out;
				overflow: hidden;
				background-color: #EDECEB;
				background-image: linear-gradient(top, #EDECEB, #F5F5F5);
				background-image: -webkit-gradient(linear, left top, left 500, color-stop(0, #EDECEB), color-stop(1, #F5F5F5));
				background-image: -moz-linear-gradient(center top, #EDECEB 0%, #F5F5F5 100%);
				background-image: -o-linear-gradient(top, #EDECEB, #F5F5F5);
			}

			/* Form properties. */

			form {
				width: 563px;
				-webkit-transition: -webkit-transform 0.25s ease;
			}

			/* Form housekeeping. */

			form.offscreen {
				-webkit-transform: translateX(-600px);
			}

			/* Form -> fieldset spacing.  Fieldsets are subsections of the form. */

			form > fieldset {
				border-radius:  5px;
				border: 1px solid transparent;
				padding: 10px 10px 10px 30px;
				margin: 5px 0;
				-webkit-transition: all 0.5s ease;
			}

			/* On the fieldsets, a little hover interaction. */

			form > fieldset:hover {
				background: rgba(255,255,255,0.1);
				border-color: rgba(0,0,0,0.1);
			}

			/* Same as above, but on active.  Helps user friendliness. */

			form > fieldset.active {
				background: rgba(255,255,255,0.25);
				border-color: rgba(0,0,0,0.25);
			}

			/* Fieldset properties. */

			fieldset {
				border: 0;
				margin: 0;
				padding: 0;
				position: relative;
			}

			/* All elements in the options fieldset should be inline instead of block. */

			fieldset#options {
				display: inline;
			}

			/* Section properties (sections reside in fieldsets to divide elements). */

			section {
				margin: 5px 0 0;
			}

			/* Give the last section some top spacing over the first. */

			section fieldset:last-child {
				margin-top: 5px;
			}

			/* Arbitrary left padding/spacing for fieldset subsections in the form section to indent them. */

			section > fieldset {
				position: relative;
				padding-left: 40px;
			}

			/* Legend properties. */

			legend {
				text-shadow: -1px 0 #DDD, 0 1px #DDD, 1px 0 #DDD, 0 -1px #DDD;
				font-size:  16px;
			}

			/* Label properties. */

			label {
				text-shadow: -1px 0 #DDD, 0 1px #DDD, 1px 0 #DDD, 0 -1px #DDD;
			}

			/* All URL/Selection labels should have their content appear below them (block). */

			label.block {
				display: block;
			}

			/* All options labels should have their content appear next to them (inline). */

			label.inline {
				display: inline;
			}

			/* Transitioning effects for active labels in the form (need to fix for legends). */

			section label, section legend {
				color: #999;
				-webkit-transition: color 0.5s ease;
			}

			.active section label, .active section legend, form > fieldset > label  {
				color:  #000;
				-webkit-transition: color 0.5s ease;
			}

			/* Textarea properties. */

			textarea {
				width: 412px;
			}

			/* Input properties. */

			input[type="text"] {
				width: 206px;
			}

			input[type="number"] {
				width: 52px;
			}

			input[type="checkbox"] {
				margin: 5px 0 5px 100px; 
			}

			input[type="button"] {
				border-radius: 2px;
				box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
				-webkit-user-select: none;
				background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5);
				border: 1px solid #AAA;
				color: #777;
				margin-bottom: 0;
				min-width: 4em;
				padding: 3px 12px;
				margin-top: 0;
				font-size: 1.1em;
			}

			/* Form buttons. */

			div#formButtons {
				display: block;
				text-align: center;
				position: relative;
			}

			div#formButtons :hover {
				font-weight: bold;
			}

			/* Overlay for generateAlert_() message. */

			.overlay {
				display: block;
				text-align: center;
				position: absolute;
				left: 50%;
				top: 50%;
				width: 350px;
				padding: 20px;
				margin: -80px 0 0 -195px;
				opacity: 0;
				background: rgba(0, 0, 0, 0.75);
				border-radius: 5px;
				color: #FFF;
				font: 1.5em/1.2 Helvetica Neue, Arial, Helvetica, sans-serif;
				-webkit-transition: all 1.0s ease;
			}

			.overlay a {
				color:  #FFF;
			}

			.overlay.visible {
				opacity: 1;
			}

		</style>

	</head>

	<!-- HTML -->

	<body onload="initPopup();">

		<div id="images">

			<input type="image" id="imageIncrement" class="disabled"  src="increment.png" onclick="clickIncrement(); return false;"/>
			<input type="image" id="imageDecrement" class="disabled" src="decrement.png" onclick="clickDecrement(); return false;" />
			<input type="image" id="imageClear" class="disabled" src="clear.png" onclick="clickClear(); return false;" />
			<input type="image" id="imageSetup" src="setup.png" onClick="toggleForm(); return false;" />

		</div>

		<div id="form">

			<form id="formSetup" >

				<fieldset id="URL">

						<legend id="legendURL"></legend>

					<section>
						<fieldset>
							<label id="labelURL" class="block" for="textareaURL"></label>
							<textarea id="textareaURL" readonly="true" onmouseup="handleURL();" onkeyup="handleURL();" ></textarea>
						</fieldset>
					</section>

					<section>
						<fieldset>
							<label id="labelSelection" class="block" for="inputSelection"></label>
							<input id="inputSelection" type="text" readonly="true" >
						</fieldset>
					</section>

				</fieldset>

				<fieldset id="Options">

					<legend id="legendOptions"></legend>

					<section>
						<fieldset id="options">
							<label id="labelIncrement" class="inline" for="inputIncrement"></label>
							<input id="inputIncrement" type="number" min="1" >
							<input id="inputZeros" type="checkbox" >
							<label id="labelZeros" class="inline" for="inputZeros"></label>
						</fieldset>
					</section>

				</fieldset>

				<div id="formButtons">
					<input id="inputAccept" type="button" onclick="submitForm();" >
					<input id="inputCancel" type="button" onclick="toggleForm();" >
				</div>

			</form>

		</div>

	</body>

	<!-- Javascript -->

	<script>

		// Global variables.

		var selectionStart = -1;
		var currentTab = new Object();
		var fieldsetGroups = document.querySelectorAll('#' + 'formSetup' + ' > fieldset'); // Nodelist containing cached reference to the fieldset groups.
		var form = document.getElementById("formSetup").addEventListener("click", this.dispatchFormClick_.bind(this));

		// Adds a listener when popup.html loads to get the current selected tab.

		window.addEventListener("load", windowLoaded, false);

		function windowLoaded() {
			chrome.tabs.getSelected(null,
				function(tab) {
					currentTab = tab;
					initForm();
				}
			);
		}

		// Sets default values for elements in the form everytime the tab is
		// updated or when the user clicks on the Setup image to get to the
		// form.

		function initForm() {

			// Fill out the form elements' contents.

			document.getElementById("textareaURL").value = currentTab.url;
			document.getElementById("inputSelection").value = smartSelection(currentTab.url);
			document.getElementById("inputIncrement").value = 1;
			document.getElementById("inputZeros").checked = true;
		}

		// Called from body onload.  Gets the current state of info (enabled)
		// and the appropriate images are loaded accordingly.  Then loads the
		// localization from messages.json for the form.

		function initPopup() {

			// Whether to show images in disabled or enabled state.

			chrome.extension.sendRequest({greeting: "getUrli"}, updateImages);

			// i18n for mesages.json.

			document.getElementById("imageIncrement").title = chrome.i18n.getMessage("popupImageIncrement");
			document.getElementById("imageDecrement").title = chrome.i18n.getMessage("popupImageDecrement");
			document.getElementById("imageClear").title = chrome.i18n.getMessage("popupImageClear");
			document.getElementById("imageSetup").title = chrome.i18n.getMessage("popupImageSetup");
			document.getElementById("legendURL").innerText = chrome.i18n.getMessage("popupLegendURL");
			document.getElementById("labelURL").innerText = chrome.i18n.getMessage("popupLabelURL"); 
			document.getElementById("labelSelection").innerText = chrome.i18n.getMessage("popupLabelSelection"); 
			document.getElementById("legendOptions").innerText = chrome.i18n.getMessage("popupLegendOptions");
			document.getElementById("labelIncrement").innerText = chrome.i18n.getMessage("popupLabelIncrement");
			document.getElementById("labelZeros").innerText = chrome.i18n.getMessage("popupLabelZeros");
			document.getElementById("inputAccept").value = chrome.i18n.getMessage("popupInputAccept");
			document.getElementById("inputCancel").value = chrome.i18n.getMessage("popupInputCancel");
		}

		// Changes the class of the images to either disabled or enabled
		// depending on the response (state of response.enabled).

		function updateImages(response) {

			var imageNodeList;

			// Get the images.  Assume they're disabled (we really don't know).

			imageNodeList = document.querySelectorAll(".disabled");

			// If the images disabled nodelist is empty, it means they're
			// currently enabled instead, so get them.

			if (imageNodeList.length == 0) {
				imageNodeList = document.querySelectorAll(".enabled");
			}

			// If urli is enabled, images should be enabled.

			if (response.enabled) {
				for (var i = 0; i < imageNodeList.length; i++) {
					imageNodeList[i].className = "enabled";
				}
			}

			// Else urli is not enabled, images should be disabled.

			else {
				for (var i = 0; i < imageNodeList.length; i++) {
					imageNodeList[i].className = "disabled";
				}
			}
		}

		// Handle URL event on mouseup and onkeyup for selection.

		function handleURL() {

			// Stores the selectionStart for later (to be returned to background.html).

			selectionStart = document.getElementById("textareaURL").selectionStart;

			// Update the "inputSelection" element to show the selected text.

			document.getElementById("inputSelection").value = window.getSelection().toString();
		}

		// Called when the user clicks on the Accept button on the form.  Checks
		// to make sure there are no errors with any of the fields, and if not,
		// passes the data back to the urli object in background.html.

		function submitForm() {

			var errorMessage = "";
			var selection = document.getElementById("inputSelection").value;
			var increment = document.getElementById("inputIncrement").value;
			var zeros = document.getElementById("inputZeros").checked;

			// ERROR If the user selected text somewhere else and released the
			// mouse in the textearea element.  Unfortunately, selectionStart
			// will be 0 and we can't disallow legitimate selections from
			// 0th position in the URL (as unlikely as they may be).

			// if (selectionStart == 0) {
			// Do something.
			// }

			// ERROR If the selected text from the URL are not digits (0-9).

			for (var i = 0; i < selection.length; i++) {
				if (selection.charCodeAt(i) < 48 || selection.charCodeAt(i) > 57) {
					errorMessage += chrome.i18n.getMessage("popupErrorSelectionNotANumber");
					break;
				}
			}

			// ERROR If the selection is blank.

			if (selection == "") {
				errorMessage += chrome.i18n.getMessage("popupErrorSelectionBlank");
			}

			// ERROR If the selection is not a part of the URL.

			if (currentTab.url.indexOf(selection) == -1) {
				errorMessage += chrome.i18n.getMessage("popupErrorSelectionNotInURL");
			}

			// ERROR If the increment is not a number.

			for (var i = 0; i < increment.length; i++) {
				if (increment.charCodeAt(i) < 48 || increment.charCodeAt(i) > 57) {
					errorMessage += chrome.i18n.getMessage("popupErrorIncrementNotANumber");
					break;
				}
			}

			// ERROR If the increment is blank.

			if (increment == "") {
				errorMessage += chrome.i18n.getMessage("popupErrorIncrementBlank");
			}

			// ERROR If the increment is 0.

			if (increment == "0") {
				errorMessage += chrome.i18n.getMessage("popupErrorIncrementZero");
			}

			// If there was an error, show the error message

			if (errorMessage != "") {
				generateAlert_(errorMessage, false);
			}

			// Else there was not an error (successful)...

			else {

				// Stores the form's information into urli, update the images
				// (enabled) and hide the form by toggling it.

				chrome.extension.sendRequest({greeting: "onPopupFormAccept", enabled: true, tab: currentTab, selection: selection, selectionStart: selectionStart, increment: increment, zeros: zeros}, function (response){});
				chrome.extension.sendRequest({greeting: "getUrli"}, updateImages);
				toggleForm();
			}
		}

		// User clicked on Increment image; need to find out if urli is enabled
		// and if the current tab is urli's tab before sending a request to
		// increment via modifyU?rliAndUpdateTab.

		function clickIncrement() {
			chrome.extension.sendRequest({greeting: "getUrli"},
				function(response) {
					if (!response.enabled || currentTab.id != response.tab.id) {
						return;
					}
					chrome.extension.sendRequest({greeting: "modifyUrliAndUpdateTab", action: "Increment"}, function(response) {});
				}
			);
		}

		// User clicked on Decrement image; need to find out if urli is enabled
		// and if the current tab is urli's tab before sending a request to
		// decrement via modifyU?rliAndUpdateTab.

		function clickDecrement() {
			chrome.extension.sendRequest({greeting: "getUrli"},
				function(response) {
					if (!response.enabled || currentTab.id != response.tab.id) {
						return;
					}
					chrome.extension.sendRequest({greeting: "modifyUrliAndUpdateTab", action: "Decrement"}, function(response) {});
				}
			);
		}

		// Send request to clear urli's info and then go to
		// updateImages to set images to "off."  Enabled should always
		// return false so a request to fetch urli seems redundant, but
		// unavoidable without adding a new function...

		function clickClear() {
			chrome.extension.sendRequest({greeting: "clearUrli"}, function(response) {});
			chrome.extension.sendRequest({greeting: "getUrli"}, updateImages);
		}

		// Shows or hides the form.  For example, this is called each time the
		// user presses the "Cancel" button to hide it and go back to the 
		// initial images popup.  Or when the "Setup" Image is pressed to do the
		// opposite.

		function toggleForm() {
			var form = document.getElementById("form");
			var images = document.getElementById("images");

			// Hide form, show images, reduce body (popup window) size.

			if(form.style.display == "block") {
				form.style.display = "none";
				images.style.display = "inline";
				document.body.style.width = "82px";
				document.body.style.height = "16px";
				document.body.style.background = "#EDECEB";
			}

			// Show form, hide images, increase body (popup window) size, update tab

			else {
				form.style.display = "block";
				images.style.display = "none";
				document.body.style.width = "auto" /*'583px' */;
				document.body.style.height = "auto"/*'287px'*/;
				document.body.style.background = "#FFFFFF";
				chrome.tabs.getSelected(null,
					function(tab) {
						currentTab = tab;
						initForm();
					}
				);
			}
		}

		// This function guesses the part of the URL the user wants to increment.
		// The algorithm currently just looks for the last number in the URL.
		// To improve, add some RegExs with digits and = . / characters in the
		// URL and look for those first.

		function smartSelection(url) {

			var selection = "";
			var urlLengthCache = url.length;
			var foundDigit = false;
			var selectionBackwards = "";

			// Start looking at the URL from the last character, not the first.

			for (var i = urlLengthCache - 1; i >= 0; i--) {

				// Already found a digit, but now found a non-digit.  This
				// must mean that's the end of the number.  Break out.

				if (foundDigit && (url.charCodeAt(i) < 48 || url.charCodeAt(i) > 57)) {
					break;
				}

				// Already found a digit, and found another digit.  Keep adding
				// to selection string and update selectionStart.

				if (foundDigit && (url.charCodeAt(i) >= 48 && url.charCodeAt(i) <= 57)) {
					selectionBackwards += url.charAt(i);
					selectionStart = i;
				}

				// Found a digit for the first time.

				if (!foundDigit && (url.charCodeAt(i) >= 48 && url.charCodeAt(i) <= 57)) {
					foundDigit = true;
					selectionBackwards += url.charAt(i);
						selectionStart = i;
				}

			}

			// The above algorithm looked at the url backwards, so the selection
			// is also backwards.  Reverse the characters of selection.

			for (var i = selectionBackwards.length - 1; i >= 0; i--) {
				selection += selectionBackwards.charAt(i);
			}

			// Set the selection range in the URL textarea and return the selection.

			document.getElementById("textareaURL").setSelectionRange(selectionStart, selectionStart + selection.length);
			return selection;
		}

		// Generate alert overlay (popup message).
		// From the sample Google extension, Proxy Settings by Mike West.

		function generateAlert_(msg, close) {
			var success = document.createElement('div');
			success.classList.add('overlay');
			success.setAttribute('role', 'alert');
			success.textContent = msg;
			document.body.appendChild(success);

			setTimeout(function() { success.classList.add('visible'); }, 10);
			setTimeout(function() {
			if (close === false) {
				// success.classList.remove('visible');
				document.body.removeChild(success);
			} else
				window.close();
			}, 3000);
		}

		// Click event handler on the form.
		// From the sample Google extension, Proxy Settings by Mike West.

		function dispatchFormClick_(e) {
			var t = e.target;

			// Walk up the tree until we hit `form > fieldset` or fall off the top

			while (t && (t.nodeName !== 'FIELDSET' || t.parentNode.nodeName !== 'FORM')) {
				t = t.parentNode;
			}

			if (t) {
				this.changeActive_(t);
				return false;
			}

			return true;
		}

		// Sets the form's active config group.
		// From the sample Google extension, Proxy Settings by Mike West.

		function changeActive_(fieldset) {

			for (var i = 0; i < fieldsetGroups.length; i++) {
				var el = fieldsetGroups[i];

				if (el === fieldset) {
					el.classList.add('active');
				} else {
					el.classList.remove('active');
				}
			}

			recalcDisabledInputs_();
		}

		// Recalculates the disabled state of the form's input elements, based
		// on the currently active group.
		// From the sample Google extension, Proxy Settings by Mike West.

		function recalcDisabledInputs_() {
			var i, j;

			for (i = 0; i < fieldsetGroups.length; i++) {
				var el = fieldsetGroups[i];
				var inputs = el.querySelectorAll("input:not([type='radio']), select, textarea");

				if (el.classList.contains('active')) {
					for (j = 0; j < inputs.length; j++) {
						inputs[j].removeAttribute('disabled');
					}

				} else {

					for (j = 0; j < inputs.length; j++) {
						inputs[j].setAttribute('disabled', 'disabled');
					}

				}
			}
		}

	</script>

</html>
